package com.ssm.basis.service.util;

import com.ssm.basis.service.office.WordUtil;
import com.ssm.basis.web.util.RequestUtil;
import com.ssm.basis.web.util.ResponseUtil;
import com.ssm.basis.web.util.WebResourceUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;

import java.time.Duration;
import java.time.Instant;

import static com.ssm.basis.service.constant.SecurityConstant.SUPPRESS_WARNING_UNCHECKED;

/**
 * https://blog.csdn.net/f641385712/article/details/88651128
 * https://blog.csdn.net/f641385712/article/details/106496142
 */
@Slf4j
public abstract class SpringHelper {
    static ApplicationContext applicationContext;
    static AutowireCapableBeanFactory beanFactory;
    static AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor;

    /**
     * Bean 并没交给 Spring 容器管理，它只是帮我们创建好，并把对应属性注入进去
     */
    @SuppressWarnings(SUPPRESS_WARNING_UNCHECKED)
    public static <T> T createBean(Class<T> beanClass) {
        try {
            return (T) beanFactory.createBean(beanClass, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false);
        } catch (BeansException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 仅注入属性
     */
    public static void autowireBean(Object existingBean) {
        // 因为是给 static 静态属性赋值，因此这里 new 一个实例做注入是可行的
        beanFactory.autowireBean(existingBean);
        // autowiredAnnotationBeanPostProcessor.processInjection(existingBean);
    }

    /**
     * 通过 class 获取 Bean
     */
    public static <T> T getBean(Class<T> clazz) {
        try {
            return applicationContext.getBean(clazz);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 事件发布
     */
    public static void publishEvent(Object event) {
        applicationContext.publishEvent(event);
    }

    /**
     * 设置 applicationContext
     */
    public static void setApplicationContext(ApplicationContext context) {
        if (applicationContext == null) {
            applicationContext = context;
            init();
        }
    }

    static void init() {
        Instant start = Instant.now();

        beanFactory = applicationContext.getAutowireCapableBeanFactory();
        autowiredAnnotationBeanPostProcessor = getBean(AutowiredAnnotationBeanPostProcessor.class);

        autowireBean(new MessageHelper() {
        });
        autowireBean(new RequestUtil() {
        });
        autowireBean(new ResponseUtil() {
        });
        autowireBean(new SsmContextHolder() {
        });
        autowireBean(new TypeConversionHelper() {
        });
        autowireBean(new WordUtil() {
        });
        autowireBean(new WebResourceUtil() {
        });

        Instant finish = Instant.now();
        long timeElapsed = Duration.between(start, finish).toMillis();
        log.debug("utils init time consuming: {} ms", timeElapsed);
    }
}